package nirvana.core.generateCode;

import cn.hutool.json.JSONUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import nirvana.core.domains.enums.EntityType;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import java.util.TreeMap;

/**
 * 【描 述】：
 * 【环 境】：J2SE 17
 * 【详 细】：
 *
 * @author 李松林
 * @version v1.0 2023-05-21 新建
 * @since 2023-05-21
 */
@Service
public class GenerateFile {


    private final Configuration freemarkerConfig;

    public GenerateFile(Configuration freemarkerConfig) {
        this.freemarkerConfig = freemarkerConfig;
    }


    /**
     * 创建单个文件
     *
     * @param param
     */
    public void generateFile(GenerateFileParam param) {

        //文件名称
        String fileName = param.getFileName();

        //输出目标路径
        String filePath = param.getFilePath();

        File filePathDir = new File(filePath);
        if (!filePathDir.exists()) {
            filePathDir.mkdirs();
        }

        //模板名称
        String templateName = param.getTemplateName();

        //将参数转化未model，给到模板
        String json = JSONUtil.toJsonStr(param);
        Map<String, Object> dataModel = JSONUtil.toBean(json, TreeMap.class);

        String targetPath = filePath + fileName;

        File file = new File(targetPath);
        //如果文件已存在，就跳过
        if (!file.exists()) {

            //找到freemarker创建
            Template template = null;
            try {
                template = freemarkerConfig.getTemplate("generateCodeTemplates/" + templateName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            //通过freemarker创建模板
            createFile(template, targetPath, dataModel);
        }
    }


    /**
     * 创建一组文件
     *
     * @param param
     */
    public void generateGroupFile(GenerateFileParam param) {


        //输出文件夹路径
        String servicePath = param.getServicePath();
        String pojoPath = param.getPojoPath();
        String mapperXmlPath = param.getMapperXmlPath();


        //是否未业务实体类
        Boolean isServerEntity = param.getIsServerEntity();


        //类名称
        String className = param.getClassName();

        //实体名称
        String entityName = param.getEntityName();

        //类名称首字母转化为小写
        String classOtherName = convertTheFirstLetterToLowerCase(className);

        param.setClassOtherName(classOtherName);


        //实体类型
        EntityType entityType = param.getEntityType();


        //业务实体模块代码
        if (EntityType.SERVICE_ENTITY.equals(entityType)) {

            //创建controller
            param.setFileName(className + "WebController.java");
            param.setFilePath(servicePath + "controller\\web\\");
            param.setTemplateName("controller.ftl");
            generateFile(param);

            //创建service
            param.setFileName(className + "Service.java");
            param.setFilePath(servicePath + "service\\in\\");
            param.setTemplateName("service.ftl");
            generateFile(param);

            //serviceImpl
            param.setFileName(className + "ServiceImpl.java");
            param.setFilePath(servicePath + "service\\impl\\");
            param.setTemplateName("serviceImpl.ftl");
            generateFile(param);
        }

        //创建repository
        param.setFileName(className + "Repository.java");
        param.setFilePath(servicePath + "repository\\in\\");
        param.setTemplateName("repository.ftl");
        generateFile(param);

        //创建repositoryImpl
        param.setFileName(className + "RepositoryImpl.java");
        param.setFilePath(servicePath + "repository\\impl\\");
        param.setTemplateName("repositoryImpl.ftl");
        generateFile(param);


        //创建mapper
        param.setFileName(className + "Mapper.java");
        param.setFilePath(servicePath + "mapper\\");
        param.setTemplateName("mapper.ftl");
        generateFile(param);

        //创建mapper.xml
        param.setFileName(className + "Mapper.xml");
        param.setFilePath(mapperXmlPath);
        param.setTemplateName("mapper_xml.ftl");
        generateFile(param);


        if (!EntityType.DATA_ENTITY.equals(entityType)) {
            //创建param
            {
                String paramPath = pojoPath + "param\\" + classOtherName + "\\";
                File pojoPathFile = new File(paramPath);
                if (!pojoPathFile.exists()) {
                    pojoPathFile.mkdirs();
                }

                param.setFileName("Create" + className + "Param.java");
                param.setFilePath(paramPath);
                param.setTemplateName("createParam.ftl");
                generateFile(param);


                param.setFileName("Edit" + className + "Param.java");
                param.setFilePath(paramPath);
                param.setTemplateName("editParam.ftl");
                generateFile(param);


                param.setFileName("Get" + className + "ListParam.java");
                param.setFilePath(paramPath);
                param.setTemplateName("getListParam.ftl");
                generateFile(param);

                param.setFileName("Get" + className + "DownListParam.java");
                param.setFilePath(paramPath);
                param.setTemplateName("getDownListParam.ftl");
                generateFile(param);

            }

            //创建vo
            {
                String voPath = pojoPath + "vo\\" + classOtherName + "\\";

                File voPathFile = new File(voPath);
                if (!voPathFile.exists()) {
                    voPathFile.mkdirs();
                }


                param.setFileName("Get" + className + "ListVo.java");
                param.setFilePath(voPath);
                param.setTemplateName("getListVo.ftl");
                generateFile(param);


                param.setFileName("Get" + className + "Vo.java");
                param.setFilePath(voPath);
                param.setTemplateName("getVo.ftl");
                generateFile(param);


                param.setFileName("Get" + className + "DownListVo.java");
                param.setFilePath(voPath);
                param.setTemplateName("getDownListVo.ftl");
                generateFile(param);

            }

            //创建dto
            {
                String dtoPath = pojoPath + "dto\\" + classOtherName + "\\";
                File dtoPathFile = new File(dtoPath);
                if (!dtoPathFile.exists()) {
                    dtoPathFile.mkdirs();
                }

                param.setFileName("Select" + className + "Dto.java");
                param.setFilePath(dtoPath);
                param.setTemplateName("selectDto.ftl");
                generateFile(param);
            }

        }

    }


    /**
     * 使用模板在置顶路径下创建文件
     *
     * @param template
     * @param targetPath
     * @param dataModel
     */
    public void createFile(Template template, String targetPath, Map<String, Object> dataModel) {
        try {
            //创建文件写入流
            Writer writer = new FileWriter(targetPath);
            //写入
            template.process(dataModel, writer);
            //关闭流
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 首字母转小写
     *
     * @param str
     * @return
     */
    public static String convertTheFirstLetterToLowerCase(String str) {
        if (!StringUtils.hasText(str)) {
            return "";
        }
        char firstChar = Character.toLowerCase(str.charAt(0));
        String result = firstChar + str.substring(1);
        return result;
    }


}
